package com.ilxqx.framework.system.service.impl;

import com.ilxqx.framework.system.constant.TableFieldConstants;
import com.ilxqx.framework.system.form.SearchForm;
import com.ilxqx.framework.system.repository.FrameworkRepository;
import com.ilxqx.framework.system.service.SearchableService;
import com.ilxqx.framework.system.util.SearchPredicateUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.Assert;

import javax.persistence.criteria.Predicate;
import java.util.List;

/**
 * 搜索服务接口实现类
 * @author venus
 */
public abstract class AbstractSearchableServiceImpl<T, ID, S extends SearchForm> extends AbstractPageableServiceImpl<T, ID> implements SearchableService<T, ID, S> {

    /**
     * 注入JPA动态条件查询实现类
     */
    private FrameworkRepository<T, ID> repository;

    public AbstractSearchableServiceImpl(FrameworkRepository<T, ID> repository) {
        super(repository);
        this.repository = repository;
    }

    /**
     * 根据搜索获取一页数据
     *
     * @param searchForm 搜索条件表单
     * @param pageable   分页和排序对象
     * @return 一页数据
     */
    @Override
    public Page<T> getSearchedPage(S searchForm, Pageable pageable) {
        Assert.notNull(searchForm, "搜索表单对象不能为空");
        return this.repository.findAll((Specification<T>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicateList = SearchPredicateUtils.buildPredicates(searchForm, root, criteriaBuilder);
            return criteriaBuilder.and(predicateList.toArray(Predicate[]::new));
        }, pageable);
    }

    /**
     * 根据操作用户和搜索获取一页数据
     *
     * @param searchForm      搜索条件表单
     * @param pageable        分页和排序对象
     * @param operationUserId 操作用户ID
     * @return 一页数据
     */
    @Override
    public Page<T> getSearchedPage(S searchForm, Pageable pageable, ID operationUserId) {
        Assert.notNull(searchForm, "搜索表单对象不能为空");
        Assert.notNull(operationUserId, "操作用户的ID不能为空");
        return this.repository.findAll((Specification<T>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicateList = SearchPredicateUtils.buildPredicates(searchForm, root, criteriaBuilder);
            // 增加当前登录用户的过滤
            predicateList.add(criteriaBuilder.equal(root.get(TableFieldConstants.OPERATION_USER_ID_FIELD_NAME), operationUserId));
            return criteriaBuilder.and(predicateList.toArray(Predicate[]::new));
        }, pageable);
    }

}
